package Common;

import com.google.common.io.Files;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.ITestResult;
import org.testng.Reporter;

import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf;

/**
 * Base class for all page-helper objects.
 * Holds functionality common for all pages, and mostly hides WebDriver interaction.
 */

public class HelperBase {

    public static final int ELEMENT_TIMEOUT = 5;
    public static final int PAGE_TIMEOUT = 10;
    public final TestManager manager;
    public final WebDriver driver;

    /**
     * Takes a reference to static TestManager instance as input.
     */

    public HelperBase(TestManager manager) {
        this.manager = manager;
        driver = manager.getDriver();
    }

    public String getBaseUrl() {
        return manager.getBaseUrl();
    }

    public WebElement findElement(By locator) {
        return driver.findElement(locator);
    }

    public List<WebElement> findElements(By locator) {
        return driver.findElements(locator);
    }

    public WebElement findElementInElement(WebElement element,By locator) {
        return element.findElement(locator);
    }

    public void type(By locator, String text) {
        driver.findElement((locator)).clear();
        driver.findElement((locator)).sendKeys(text);
    }

    public void selectByValue(By locator, String value) {
        new Select(driver.findElement(locator)).selectByValue(value);
    }

    public void selectByIndex(By locator, int index) {
        new Select(driver.findElement(locator)).selectByIndex(index);
    }

    public void selectByText(By locator, String text) {
        new Select(driver.findElement(locator)).selectByVisibleText(text);
    }

    public void click(By locator) {
        findElement((locator)).click();
    }

    public String getText(By locator) {
        return findElement((locator)).getText();
    }

    public boolean textIsPresent(By locator, String text) {
        return getText(locator).equals(text);
    }

    public String getValue(By locator) {
        return findElement((locator)).getAttribute("value");
    }

    public void openUrl(String string) {
        driver.get(string);
    }

    public void refreshPage() {
        driver.navigate().refresh();}

    public boolean isElementsLocated(By locator){
        return driver.findElements(locator).size() >= 2;
    }

    public boolean isElementPresent(By locator) {
        try {
            waitForElementInDOM(locator);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public boolean isElementInElementPresent(By locator2, By locator) {
        try {
            driver.findElement(locator).findElements(locator2);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public boolean isElementVisible(By locator) {
        try {
            waitForElementInvisible(locator);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public void waitForElementVisible(By locator) {
        waitFor(visibilityOfElementLocated(locator));
    }

    public void waitForElementInDOM(By locator) {
        waitFor(presenceOfElementLocated(locator));
    }

    public void waitForElementInvisible(By locator) {
        waitFor(invisibilityOfElementLocated(locator));
    }

    public void waitForElementRefreshed(WebElement webElement) {
        waitFor(refreshed(visibilityOf(webElement)));
    }

    public void moveTheMouse(WebElement locator) {
        new Actions(driver).moveToElement(locator).perform();
    }

    public void moveByOffset (int x, int y) {
        new Actions(driver).moveByOffset(x, y).perform();
    }

    public void moveTheMouseToOffset(WebElement locator,int x, int y) {
        new Actions(driver).moveToElement(locator,x,y).perform();
    }

    public void clickAndHold() {
        new Actions(driver).clickAndHold().perform();
    }

    public void releaseMouse() {
        new Actions(driver).release().perform();
    }

    public void mouseMoving(WebElement locator, int x, int y, int endX, int endY) {
        moveTheMouse(locator);
        moveByOffset(x, y);
        sleeper(500);
        clickAndHold();
        sleeper(500);
        moveByOffset(endX, endY);
        sleeper(500);
        releaseMouse();
    }
    public boolean isSizeIncreased(WebElement element, int x, int dx){
        System.out.println(element.getSize().getWidth());
        return element.getSize().getWidth() == x+dx;
    }

    protected void waitFor(ExpectedCondition<?> condition) {
        new WebDriverWait(driver, ELEMENT_TIMEOUT).until(condition);
    }

    protected boolean switchToWindow(int numWindow) {
        if((numWindow + 1) <= driver.getWindowHandles().toArray().length){
            driver.switchTo().window(driver.getWindowHandles().toArray()[numWindow].toString());
            return true;
        }
        else{
            return false;
        }
    }

    protected void closeCurrentWindow() {
        driver.close();
    }

    public void openBaseUrl() {
        openUrl(getBaseUrl());
    }

    public void takeScreenShot(ITestResult result) throws IOException {
        if (!result.isSuccess()) {
            File ScreenShot = new File(result.getMethod().getMethodName() + ".png");
            ScreenShot.delete();
            File ScreenShotTempFile = ((TakesScreenshot) driver)
                    .getScreenshotAs(OutputType.FILE);
            Files.copy(ScreenShotTempFile, ScreenShot);
            Reporter.log("<a href='" + ScreenShot.getName() + "'>"
                    + result.getMethod().getMethodName() + " screenshot</a>");
        }
    }

    public void ClearField(By locator){
        findElement(locator).clear();
    }

    public void sleeper(int n) {
        try {
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void delCookies() throws InterruptedException {
        driver.manage().deleteAllCookies();
        //driver.navigate().refresh();
        Thread.sleep(2000);
    }

    public void userLogin(By locator,By locator2,By locator3, String login, String password) {
        type(locator, login);
        type(locator2, password);
        click(locator3);
    }

    public int getElementHeight(WebElement element) {
        return element.getSize().getHeight();
    }
    public int getElementWidth(WebElement element) {
        return element.getSize().getWidth();
    }

}
